package com.sl.biz.modular.process.helper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.sl.core.domain.dto.*;
import com.sl.core.utils.JsonUtil;
import com.sl.core.engine.utils.BeanUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.sl.core.engine.plugin.ProcessPluginLoaderManager.LATEST_TAG;

/**
 * todo 还没有完成 异步执行实现思路，在要异步的连线上插一个对象合并组件，再把这条线后面的所有组件单独抽成一个流程，然后异步执行这个流程。
 */
@Slf4j
public class ProcessFrontFileToBackFileHelper {


    public static final ProcessFrontFileToBackFileHelper INSTANCE = new ProcessFrontFileToBackFileHelper();

    public static SquareLakeLayout toConf(String backFile) {
        SquareLakeLayout bean = JsonUtil.toBean(backFile, SquareLakeLayout.class);
        return bean;
    }

    public SquareLakeLayout frontToBack(String map) {
        return frontToBack(JsonUtil.toMap(map), null);
    }

    public SquareLakeLayout frontToBack(Map<String, Object> map) {
        return frontToBack(map, null);
    }

    public SquareLakeLayout frontToBack(Map<String, Object> map, String processName) {

        if (MapUtil.isEmpty(map)) {
            return null;
        }

        Transformation transformation = buildTransformation(map, processName);
        SquareLakeLayout squareLakeLayout = new SquareLakeLayout();
        squareLakeLayout.setTransformation(transformation);
        return squareLakeLayout;
    }

    public Transformation buildTransformation(Map<String, Object> map, String processName) {
        if (MapUtil.isEmpty(map)) {
            return null;
        }
        Transformation transformation = Transformation.basic(processName, "");
        //注释的不需要
        List edges = MapUtil.get(map, "edges", List.class);
        transformation.setOrder(buildOrder(edges));

        List nodes = MapUtil.get(map, "nodes", List.class);
        transformation.setStep(buildStep(nodes));
        transformation.rebuild();
        return transformation;
    }

    public TransformationOrder buildOrder(List<Map<String, Object>> nodeList) {
        TransformationOrder basic = TransformationOrder.basic();
        if (CollUtil.isEmpty(nodeList)) {
            return basic;
        }
        nodeList.stream().filter(v -> {
            //移除备注
            String type = MapUtil.getStr(v, "type");
            return !StrUtil.equalsAnyIgnoreCase(type, "remark-line");
        }).forEach(v -> {
            Boolean disabled = BeanUtil.getBool(v, "properties.disabled");
            basic.addHop(BeanUtil.getStr(v, "sourceNodeId"), BeanUtil.getStr(v, "targetNodeId"), disabled ? "N" : "Y");
        });
        return basic;
    }

    public List<TransformationStep> buildStep(List<Map<String, Object>> nodeList) {
        if (CollUtil.isEmpty(nodeList)) {
            return Collections.emptyList();
        }
        return nodeList.stream().filter(v -> {
            String type = MapUtil.getStr(v, "type");
            //移除备注
            return !StrUtil.equalsAnyIgnoreCase(type, "remark-node");
        }).map(v -> {
            Map<String, Object> params = Maps.newHashMap();
            //基础配置
            Map<String, Object> basicConfig = BeanUtil.getMap(v, "properties.basicConfig");
            if (MapUtil.isNotEmpty(basicConfig)) {
                params.putAll(basicConfig);
            }
            //组件配置
            Map<String, Object> componentConfig = BeanUtil.getMap(v, "properties.componentConfig");
            if (MapUtil.isNotEmpty(componentConfig)) {
                params.putAll(componentConfig);
            }

            String type = findType(v);
            TransformationStep transformationStep = TransformationStep.basic(MapUtil.getStr(v, "id"), type, "N", params);

            return transformationStep;
        }).collect(Collectors.toList());


    }

    private String findType(Map<String, Object> v) {
        String str = BeanUtil.getStr(v, "properties.component.type");
        Boolean bool = BeanUtil.getBool(v, "properties.basicConfig.systemFlag");
        String version = BeanUtil.getStr(v, "properties.basicConfig.version");
        String versionId = BeanUtil.getStr(v, "properties.basicConfig.versionId");

        if (StrUtil.equals(version, LATEST_TAG)) {
            return str;
        }
        if (StrUtil.isBlank(versionId)) {
            return str;
        }
        return versionId;
    }


}
